#define _USING_V110_SDK71_ 1
#include <Python.h>
#include <stdio.h>
#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
#include <ndarrayobject.h>


#include <windows.h>
#include <windowsx.h>
#include <string.h>
#pragma comment(lib, "gdi32.lib")
#pragma comment(lib, "user32.lib")
#pragma comment(lib, "kernel32.lib")


// 800 x 600


HANDLE ben;
HWND global_hwnd;
BYTE *pbBitmap;


DWORD WINAPI Proc1(
  LPVOID lpParameter   // thread data
);

LRESULT CALLBACK WndProc(
    HWND hwnd,
    UINT uMsg,
    WPARAM wParam,
    LPARAM lParam
    );








static PyObject *my_blit(PyObject *dummy, PyObject *args)
{
    PyObject *arg1=NULL;
    PyObject *arr1=NULL;

    // if (!PyArg_ParseTuple(args, "OOO!", &arg1, &arg2,
    //     &PyArray_Type, &out)) return NULL;
    if (!PyArg_ParseTuple(args, "O!", &PyArray_Type, &arg1)) return NULL;

    arr1 = PyArray_FROM_OTF(arg1, NPY_BYTE, NPY_ARRAY_IN_ARRAY);
    if (arr1 == NULL) return NULL;

    npy_intp *shape = PyArray_SHAPE(arr1);
    npy_byte *array = (npy_byte*)PyArray_DATA(arr1);
    // printf("%d %d %d\n", (int)shape[0], (int)shape[1], (int)shape[2]);
    if ((int)shape[2] != sizeof(RGBQUAD)) {
        puts("need 4 bytes pixel");
        return NULL;
    }


    // MY TIME //
    RECT rect;
    HDC hDC = GetDC(global_hwnd);
    GetWindowRect(global_hwnd, &rect);
    // f() begin
    int nWidth = rect.right - rect.left;
    int nHeight = rect.bottom - rect.top;
    HDC hDCMem = CreateCompatibleDC(hDC);
    BITMAPINFO bi = { 0 };
    {
        bi.bmiHeader.biSize = sizeof(bi.bmiHeader);
        bi.bmiHeader.biWidth = nWidth;
        bi.bmiHeader.biHeight = nHeight;
        bi.bmiHeader.biPlanes = 1;
        bi.bmiHeader.biBitCount = 32;
        bi.bmiHeader.biCompression = BI_RGB;
    }
    // BYTE *pbBitmap; // 输出指针
    HBITMAP hBitmap = CreateDIBSection(NULL, &bi, DIB_RGB_COLORS, (void**)&pbBitmap, NULL, 0);
    RGBQUAD *pRGB;
    LONG nPixels;
    // printf("%d\n", (int)sizeof(RGBQUAD));
    // memcpy(void *destin, void *source, unsigned n)
    memcpy((void*)pbBitmap, (void*)array, sizeof(RGBQUAD) * (int)shape[0] * (int)shape[1]);
    // for (pRGB = (RGBQUAD *)pbBitmap, nPixels = nWidth * nHeight; nPixels > 0; ++pRGB, --nPixels)
    // {

    //     ULONG nRed = pRGB->rgbRed;
    //     ULONG nGreen = pRGB->rgbGreen;
    //     ULONG nBlue = pRGB->rgbBlue;


    //     pRGB->rgbRed = rand()%256;
    //     pRGB->rgbGreen = rand()%256;
    //     pRGB->rgbBlue = rand()%256;
    // }
    SelectObject(hDCMem, hBitmap);
    BitBlt(hDC, 0, 0, nWidth, nHeight, hDCMem, 0, 0, SRCCOPY);
    DeleteObject(hBitmap);
    DeleteDC(hDCMem);
    // f() end
    ReleaseDC(global_hwnd, hDC);

    // GOOD //







    Py_DECREF(arr1);
    Py_INCREF(Py_None);
    return Py_None;

 fail:
    Py_XDECREF(arr1);
    return NULL;
}







static PyMethodDef win1271_methods[] = {
    { "blit", my_blit, METH_VARARGS, "blit the data" },
    { NULL, NULL, 0, NULL }     // sentinel
};






















BOOL WINAPI DllMain(
    HINSTANCE hinstDLL,  // handle to DLL module
    DWORD fdwReason,     // reason for calling function
    LPVOID lpReserved )
{
    switch(fdwReason)
    {
        case DLL_PROCESS_ATTACH:
            {
                ben = GetModuleHandle(NULL);
                HANDLE thread1;
                thread1 = CreateThread(NULL, 0, Proc1, NULL, 0, NULL);
            }
            break;

        case DLL_THREAD_ATTACH:
         // Do thread-specific initialization.
            break;

        case DLL_THREAD_DETACH:
         // Do thread-specific cleanup.
            break;

        case DLL_PROCESS_DETACH:
         // Perform any necessary cleanup.
            break;
    }
    return TRUE;  // Successful DLL_PROCESS_ATTACH.
}



DWORD WINAPI Proc1 (LPVOID lpParameter)
{
    static TCHAR szAppName [] = TEXT ("win1271") ;
    HWND hwnd ;
    MSG msg ;
    WNDCLASS wndclass ;
    {
        wndclass.style = CS_HREDRAW | CS_VREDRAW ;
        wndclass.lpfnWndProc = WndProc ;
        wndclass.cbClsExtra = 0 ;
        wndclass.cbWndExtra = 0 ;
        wndclass.hInstance = (HINSTANCE)ben ;
        // wndclass.hIcon = LoadIcon (NULL, IDI_INFORMATION) ;
        wndclass.hIcon = NULL ;
        wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
        wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
        wndclass.lpszMenuName = NULL ;
        wndclass.lpszClassName = szAppName ;
    }
    if (!RegisterClass (&wndclass))
    {
        MessageBox (NULL, TEXT ("This program requires Windows NT!"),
        szAppName,
        MB_ICONERROR) ;
        return 0 ;
    }
    hwnd = CreateWindow ( szAppName, TEXT ("win1271 - Demo"),
        // WS_OVERLAPPED|WS_EX_LAYERED |WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX,
        WS_POPUP ,
        CW_USEDEFAULT, CW_USEDEFAULT,
        800, 600,       //
        NULL, NULL, (HINSTANCE)ben, NULL) ;


        global_hwnd = hwnd;


    // ShowWindow (hwnd, iCmdShow) ;
    ShowWindow (hwnd, SW_SHOWNORMAL) ;
    UpdateWindow (hwnd) ;
    while (GetMessage (&msg, NULL, 0, 0))
    {
        TranslateMessage (&msg) ;
        DispatchMessage (&msg) ;
    }
    return msg.wParam ;
}

RECT move_record;   // x, y, width, height

LRESULT CALLBACK WndProc (  HWND hwnd, UINT message, WPARAM wParam,LPARAM
lParam)
{
    PAINTSTRUCT ps ;
    RECT rect;
    HDC hdc;
    switch (message)
    {
        // case WM_MOUSEMOVE:
        // hdc = GetDC(hwnd);
        // GetWindowRect(hwnd, &rect);
        // f(hdc, rect);
        // ReleaseDC(hwnd, hdc);
    case WM_LBUTTONDOWN:
        SendMessage(hwnd, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0);
        // GetWindowRect (hwnd, &move_record);
        // move_record.right -= move_record.left;
        // move_record.bottom -= move_record.top;
        // move_record.left -= GET_X_LPARAM (lParam);
        // move_record.top -= GET_Y_LPARAM (lParam);
        return 0;
    case WM_MOUSEMOVE:
        // if (wParam & MK_LBUTTON || wParam & MK_RBUTTON) {
        //     MoveWindow(hwnd,
        //         GET_X_LPARAM (lParam) + move_record.left, GET_Y_LPARAM (lParam) + move_record.top,
        //         move_record.right, move_record.bottom, TRUE);
        // }
        return 0 ;
    case WM_CREATE:
        return 0 ;
    case WM_SIZE:
        return 0 ;
    case WM_PAINT:
        //~ hdc = BeginPaint (hwnd, &ps) ;
        //~ GetWindowRect(hwnd, &rect);
        //~ f(hdc, rect);
        //~ ReleaseDC(hwnd, hdc);
        //~ EndPaint (hwnd, &ps) ;
        BeginPaint (hwnd, &ps) ;
        EndPaint (hwnd, &ps) ;
        return 0 ;
    case WM_DESTROY:
        PostQuitMessage (0) ;
        return 0 ;
    }
    return DefWindowProc (hwnd, message, wParam, lParam) ;
}



































// PyMODINIT_FUNC initbird(void)
// {
//     PyImport_AddModule("bird");
//     Py_InitModule("bird", bird_methods);
// }


static struct PyModuleDef win1271_struct =
{
    PyModuleDef_HEAD_INIT,
    "win1271", /* name of module */
    "",          /* module documentation, may be NULL */
    -1,          /* size of per-interpreter state of the module, or -1 if the module keeps state in global variables. */
    win1271_methods
};

PyMODINIT_FUNC PyInit_win1271(void)
{
    import_array();
    return PyModule_Create(&win1271_struct);
}




